const std = @import("std");
const builtin = @import("builtin");
const csr = @import("riscv").csr;
const root = @import("kernel.zig");

const print = root.print;
extern fn trap_vector() callconv(.c) void;

pub fn init() void {
    // set the trap-vector base-address for machine-mode
    csr.mtvec.write(@intFromPtr(&trap_vector));
}

export fn trap_handler(epc: u32, mcause: csr.mcause.Type()) u32 {
    var return_pc: u32 = epc;
    print("\x1b[32m" ++ "{f}\n" ++ "\x1b[m", .{mcause});

    if (mcause.interrupt) {
        // Asynchronous trap - interrupt
        switch (mcause.code.interrupt) {
            .@"Machine software interrupt" => {},
            .@"Machine timer interrupt" => {},
            .@"Machine external interrupt" => {},
            else => print("unknown async exception!\n", .{}),
        }
    } else {
        // Synchronous trap - exception
        print("Sync exceptions!, code = {}\n", .{mcause.code.exception});
        //@panic("OOPS! What can I do!");
        return_pc += 4;
    }

    return return_pc;
}

pub fn tests() void { // safe, fast, small 模式下这个函数都被优化没了。。
    // Synchronous exception code = 7
    // Store/AMO access fault
    //const ptr = @intToPtr(?*u32, 0x0);
    //ptr.* = 100;
    //
    //@intToPtr(*u32, 0).* = 100; // pointer type '*u32' does not allow address zero
    //@intToPtr([*c]u32, 0).* = 100; // c 指针没有限制
    @as(*allowzero volatile usize, @ptrFromInt(0)).* = 100; // 加 volatile 才不会被优化

    // Synchronous exception code = 5
    // Load access fault
    const a = @as(*allowzero volatile usize, @ptrFromInt(0)).*;
    _ = a;

    print("Yeah! I'm return back from trap!\n", .{});
}
